from django.core.urlresolvers import reverse
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django_redis import get_redis_connection
import json
from goods.models import GoodsSKU

# Create your views here.
from django.views.generic import View


class DeleteCartView(View):
    """删除购物车数据"""
    def post(self, request):
        sku_id = request.POST.get('sku_id')
        # 校验参数
        if not sku_id:
            return JsonResponse({'code':1, 'message':'参数错误'})
        # 判断用户是否登陆
        if request.user.is_authenticated():
            # 查询redis数据
            redis_conn = get_redis_connection('default')
            user_id = request.user.id
            # 商品不存在就忽略，不会报错
            redis_conn.hdel('cart_%s' %user_id, sku_id)

        else:
            # 删除ckkie中购物车数据
            cart_json = request.COOKIES.get('cart')
            if cart_json:
                cart_dict = json.loads(cart_json)
                if sku_id in cart_dict:
                    del cart_dict[sku_id]
                # 重新写入
                response = JsonResponse({'code':0, 'message':'删除购物侧成功'})
                response.set_cookie('cart', json.dumps(cart_dict))
                return response

        return JsonResponse({'code': 0, 'message': '删除成功'})






class UpdateCartView(View):
    """更新购物车数据"""
    def post(self, request):
        # 获取sku_id,count, 幂等，直接赋值，而不是+1 -1
        sku_id = request.POST.get('sku_id')
        count = request.POST.get('count')
        # 校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 1, 'message':'参数不完整'})

        # 判断商品是否存在
        try:
            sku = GoodsSKU.objects.get(id=sku_id)
        except GoodsSKU.DoesNotExist:
            return JsonResponse({'code':2, 'message': '商品不存在'})

        # 判断count是不是整数
        try:
            count = int(count)
        except Exception:
            return JsonResponse({'code':3, 'message':'数量有误'})

        # 判断库存
        if count > sku.stock:
            return JsonResponse({'code':4, 'message':'库存不足'})

        # 判断用户是否登陆
        if request.user.is_authenticated():
            # 如果登陆， 将修改的购物车数据存储到redis中
            redis_conn = get_redis_connection('default')
            user_id = request.user.id
            # 数值为更新后的数量
            redis_conn.hset('cart_%s' % user_id, sku_id, count)
            return JsonResponse({'code': 0, 'message': '添加购物车成功'})

        else:
            # 未登陆的话，将修改后的数据写入cookie
            cart_json = request.COOKIES.get('cart')
            # 存在的话，转为字典
            if cart_json:
                cart_dict = json.loads(cart_json)
            else:
                cart_dict = {}

            cart_dict[sku_id] = count
            new_cart_json = json.dumps(cart_dict)

            # 响应结果
            response = JsonResponse({'code':0, 'message':'添加购物车成功'})

            # 写入cookie
            response.set_cookie('cart', new_cart_json)
            return response



class CartInfoView(View):
    """获取购物车数据，展示购物车页面"""

    def get(self, request):
        """提供购物车页面，不需要请求参数"""
        # 查询购物车数据， 如果登陆，从redis中读取，没有登陆
        # 从cookie中读取
        if request.user.is_authenticated():
            # 创建redis链接对象
            redis_conn = get_redis_connection('default')
            user_id = request.user.id
            # 获取该用户在redis中的购物车数据
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)


        else:
            # 没有登陆，从cookie中获取
            cart_json = request.COOKIES.get('cart')
            # 判断用户是否操作过购物车的cookie
            if cart_json:
                cart_dict = json.loads(cart_json)

            else:
                cart_dict = None
        # 二者都是sku_id：count的形式存储
        # 遍历保留所有sku
        skus = []
        # 总金额
        total_amount = 0
        # 总数
        total_count = 0
        # 遍历字典，查询
        for sku_id, count in cart_dict.items():
            # 查询商品
            try:
                sku = GoodsSKU.objects.get(id=sku_id)
            except GoodsSKU.DoesNotExist:
                # 商品不存在，继续遍历
                continue
            count = int(count)
            amount = sku.price * count
            # 将数据保存到对象中
            sku.amount = amount
            sku.count = count

            # 模型列表
            skus.append(sku)

            total_amount += amount
            total_count += count

        context = {
            'skus': skus,
            'total_amount': total_amount,
            'total_count': total_count,

        }

        return render(request, 'cart.html', context)










class AddClassView(View):
    """
    添加购物出数据, 通过ajax进行数据传输
    后续：更改购物车数据不限定登陆用户，
    未登陆用户的数据存入cookie中
    当登陆
    成功后，将未登陆时的数据与用户redis中数据合并

    """

    def post(self, request):

        # 判断用户是否登陆
        # if not request.user.is_authenticated():
        #     return JsonResponse({'code': 1, 'message': '用户未登陆'})

        # 接收数据： user_id, sku_id, count
        # user_id = request.user.id
        # 商品id，ajax提交的
        sku_id = request.POST.get('sku_id')
        # 商品数量
        count = request.POST.get('count')

        # 校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 2, 'message': '参数不完整'})
        # 判断商品是不是存在
        try:
            sku = GoodsSKU.objects.get(id=sku_id)
        except GoodsSKU.DoesNotExist:
            return JsonResponse({'code': 3, 'message': '商品不存在'})

        # 判断count是不是为整数
        try:
            count = int(count)
        except Exception:
            return JsonResponse({'code': 4, 'message': '数量错误'})

            # # 判断库存， 将目前的和已经加入的加起来
            # # 所以要先判定是不是已经存在
            # # 操作redis数据库， 存储商品到购物车，先查询
            # redis_conn = get_redis_connection('default')
            # # 需要先获取是不是已经存在
            # origin_count = redis_conn.hget('cart_%s' % user_id, sku_id)
            # # 如果商品存在存在， 就累加，反之，就把新的商品和数量添加到该用户的购物车
            # if origin_count is not None:
            #     # 从redis中查询出来的为字典，但是里面内容为字节型，要转化
            #     count += int(origin_count)
            # # 判断库存，计算count与库存比较
            # if count > sku.stock:
            #     return JsonResponse({'code':5, 'message':'库存不足'})

        # 提示：无论是否登陆状态，都需要获取suk_id,count,校验参数。。。
        # 所以等待参数校验结束后，再来判断用户是否登陆
        # 如果用户已登录，就保存购物车数据到redis中
        if request.user.is_authenticated():
            # 用户id
            user_id = request.user.id
            # 同样判定用户redis中是否有cookie中的数据，如果有则合并，没有则添加
            redis_conn = get_redis_connection('default')
            origin_count = redis_conn.hget('cart_%s' % user_id, sku_id)

            # 判定是不是有, redis中字节类型转化为int
            if origin_count:
                count += int(origin_count)

            # 最终购物车与库存比较
            if count > sku.stock:
                return JsonResponse({'code': 5, 'message': '库存不足'})

            # 写入到redis， 更新数据库中的购物车数据
            redis_conn.hset('cart_%s' % user_id, sku_id, count)
            # 展示购物车数量
            cart_num = 0
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)
            for val in cart_dict.values():
                cart_num += int(val)

            # json方式响应购物车结果
            return JsonResponse({'code': 0, 'message': '添加购物车成功', 'cart_num': cart_num})
        else:
            # 如果用户没有登陆，将购物车信息存入cookie
            # 合并或者赋值
            cart_json = request.COOKIES.get('cart')

            # 判断购物车cookie数据是否存在
            if cart_json:
                # 将json转化为字典,反之为dumps
                cart_dict = json.loads(cart_json)
            else:
                # 如果用户没有操作购物车， 就给个空字典
                cart_dict = {}
            if sku_id in cart_dict:
                # 如果cookie中有这个商品记录，则直接进行求和；如果cookie中没有这个商品记录，则将记录设置到购物车cookie中
                count += cart_dict[sku_id]
            # 判断最终的count与库存
            if count > sku.stock:
                return JsonResponse({'code': 6 , 'message': '库存不足'})

            # 设置最终的商品数量到购物车
            cart_dict[sku_id] = count

            # 计算购物车总数
            cart_num = 0
            for val in cart_dict.values():
                cart_num += val
            # 转化为json，存入cookie
            cart_str = json.dumps(cart_dict)

            # 将购物车数据写入cookie中
            response = JsonResponse({'code':0, 'message': '添加购物车成功', 'cart_num': cart_num})
            response.set_cookie('cart', cart_str)
            # 但是跳转到其他详情页的时候，购物车还没数据，需要到goods中修改相应代码
            return response


